home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Leser 15
/
Amiga Plus Leser CD 15.iso
/
Tools
/
Development
/
mmu
/
MuManual
/
C_Sources
/
IndirectTest.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-03-12
|
10KB
|
324 lines
/*********************************************************
** IndirectTest **
** **
** Test indirect page descriptors of the MuLib **
** Release 1.01 **
** **
** © 19.03.2000 Thomas Richter **
*********************************************************/
/// Includes
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <mmu/context.h>
#include <mmu/mmutags.h>
#include <mmu/descriptor.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/mmu.h>
#include <string.h>
///
/// Defines
///
/// Protos
int __saveds main(void);
int RunTests(void);
void DumpData(UBYTE *src,ULONG size);
///
/// Statics
char version[]="$VER: IndirectTest 1.01 (19.03.2000) © THOR";
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct MMUBase *MMUBase;
///
///main
int __saveds main(void)
{
int rc=25;
/*
** Since we want to link without startup code,
** we need to open the system libraries here...
*/
SysBase = *((struct ExecBase **)(4L));
/*
** Open DOS and MMU
**/
if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37L)) {
if (MMUBase = (struct MMUBase *)OpenLibrary("mmu.library",42L)) {
rc = RunTests();
CloseLibrary((struct Library *)MMUBase);
} else {
Printf("IndirectTest failed: This program requires the mmu.library V42 or better.\n");
rc = 10;
}
/*
** Everything above 64 is a system
** error code we print over the console.
*/
if (rc>64) {
PrintFault((LONG)rc,"IndirectTest failed");
rc = 10;
}
CloseLibrary((struct Library *)DOSBase);
}
return rc;
}
///
/// RunTests
int RunTests(void)
{
struct MMUContext *ctx;
struct MinList *ctxl;
ULONG pagesize;
ULONG *descriptor,*descriptorp;
ULONG values[2];
ULONG props[2];
UBYTE *page,*pagep[2];
int rc=25;
/*
** Get the context we're currently using
** and its page size
** furthermore, allocate a page.
*/
ctx = CurrentContext(NULL);
pagesize = GetPageSize(ctx);
page = AllocAligned(pagesize*2,MEMF_PUBLIC|MEMF_CLEAR,pagesize);
if (page) {
/*
** Now allocate memory for the descriptor
** this must be long-word aligned, hence
** an AllocMem is fine here.
** However, we need to know the physical location
** of the descriptor.
*/
descriptor = AllocMem(sizeof(ULONG),MEMF_PUBLIC);
if (descriptor) {
/*
** Compute physical locations
** We do not assume that PhysicalLocation()
** truncates the address. All values are
** long/page aligned longs/pages, hence never cross a
** page boundary.
*/
descriptorp = descriptor;
PhysicalLocation(ctx,(void **)&descriptorp,&pagesize);
/* And now for the pages */
pagep[0] = page;
props[0] = PhysicalLocation(ctx,(void **)&pagep[0],&pagesize);
pagep[1] = page+pagesize;
props[1] = PhysicalLocation(ctx,(void **)&pagep[1],&pagesize);
if (pagep[0] && pagep[1] && descriptorp) {
/*
** Lock the context and make a backup of it.
**
*/
LockMMUContext(ctx);
if (ctxl=GetMapping(ctx)) {
/*
** Pre-calculate the values for the descriptors.
** The first descriptor maps the page to its TRUE physical
** location, the second one to the ROM, writeprotecting
** it.
** Note that we need to use the physical addresses here.
**
** MAPP_ROM protection must be archived by setting this
** property bit "one level up".
**
** We furthermore set USED and MODIFIED to avoid unnecessary
** MMU writebacks, and transfer the old properties back
** into the descriptor properties
**
** Note that this call returns BAD_DESCRIPTOR in case
** of an error, not NULL.
*/
values[0] = BuildIndirect(ctx,(ULONG)(pagep[0]),props[0]|MAPP_USED|MAPP_MODIFIED);
values[1] = BuildIndirect(ctx,(ULONG)(pagep[1]),props[1]|MAPP_USED|MAPP_WRITEPROTECTED);
if ((values[0] != BAD_DESCRIPTOR) &&
(values[1] != BAD_DESCRIPTOR)) {
/*
** Install the descriptor
** The first parameter is the physical address
** of the descriptor, the second the
** logical address of the page
** and the last the descriptor to install
*/
SetIndirect(descriptorp,(ULONG)page,values[0]);
/*
** Now install this descriptor
** We set this to MAPP_ROM because we want emulated
** ROM writeprotection.
** This is ignored if the descriptor itself is
** not write protected anyhow.
** We need the physical location of the descriptor
** here.
*/
if (SetProperties(ctx,MAPP_ROM|MAPP_INDIRECT,MAPP_ROM|MAPP_INDIRECT,
(ULONG)page,pagesize,
MAPTAG_DESCRIPTOR,descriptorp,
TAG_DONE)) {
if (RebuildTree(ctx)) {
/* Everything's fine.
** copy some dummy data into the page
*/
memset(page,'*',(size_t)pagesize);
/* now print parts of it */
DumpData(page,0x10);
/*
** install the other descriptor
*/
SetIndirect(descriptorp,(ULONG)page,values[1]);
/*
** Dump it again. Should be all zero now.
*/
DumpData(page,0x10);
/* Try to write to it. This should
** fail quietly.
*/
*page = 'A';
/* And dump it again */
DumpData(page,0x10);
/*
** install the old descriptor
** again
*/
SetIndirect(descriptorp,(ULONG)page,values[0]);
/*
** Now reset the context data.
** Disable the MAPP_ROM and MAPP_INDIRECT
** features. This call shouldn't fail or
** we are in trouble
*/
if (SetProperties(ctx,0,MAPP_ROM|MAPP_INDIRECT,
(ULONG)page,pagesize,TAG_DONE)) {
/* Restore the former MMU tree */
if (RebuildTree(ctx)) {
/*
** everything is fine now.
*/
rc = 0;
}
}
if (rc) {
/*
** We're now in trouble.
** The old context couldn't be restored.
** Therefore, we do not release the descriptors
** such that the accesses are at least right,
** and restore the high-level by SetPropertyList()
** below. This will cause a mild memory leak,
** but the system will be fine.
*/
Printf("IndirectTest: Can't restore the context.\n");
descriptor = NULL;
}
} else Printf("IndirectTest: Building the context failed.\n");
} else Printf("IndirectTest: Can't install the new descriptor.\n");
/*
** In case of an error, we restore now the high
** level of the context.
** This is all we could do.
** The high-level looks then fine again,
** and the low level contains either an
** indirect descriptor which we can't get
** rid of, but which maps ok, or is
** unchanged. The system will be fine
** in both cases.
*/
if (rc) {
SetPropertyList(ctx,ctxl);
}
} else Printf("Can't build the new descriptors.\n");
/* Release the mapping */
ReleaseMapping(ctx,ctxl);
} else rc = ERROR_NO_FREE_STORE;
/*
** Release the MMU Context lock
*/
UnlockMMUContext(ctx);
} else Printf("IndirectTest: Can't perform the logical to physical translation.\n");
/*
** now release the descriptor
*/
if (descriptor) {
FreeMem(descriptor,sizeof(ULONG));
}
} else rc = ERROR_NO_FREE_STORE; /* of if descriptor */
FreeMem(page,pagesize*2);
} else rc = ERROR_NO_FREE_STORE; /* of if page */
return rc;
}
///
/// DumpData
void DumpData(UBYTE *src,ULONG size)
{
/*
** A pretty dumb memory dump
*/
Printf("Memory contents at 0x%08lx : ",src);
while(size) {
Printf("%02lx ",*src);
src++;
size--;
}
Printf("\n");
}
///